package admin

import BaseViewModel
import LoadingStatus
import LocationsRepository
import ObjectsRepository
import admin.models.AdminObjectsEvent
import admin.models.AdminObjectsViewState
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import models.LocationUi
import my.models.ComponentUi
import my.models.ComputerUi
import my.models.MyObject

class AdminObjectsViewModel(
    private val repository: ObjectsRepository, private val locationsRepo: LocationsRepository
) : BaseViewModel<AdminObjectsViewState, AdminObjectsEvent>(
    initialState = AdminObjectsViewState()
) {
    override fun obtainEvent(event: AdminObjectsEvent) {
        when (event) {
            is AdminObjectsEvent.DeleteObject -> deleteObject(event.obj)
            AdminObjectsEvent.LoadObjects -> if (viewState.loadingStatus != LoadingStatus.FullyLoad) loadObjects()
        }
    }

    private fun deleteObject(obj: MyObject) {
        when (obj) {
            is ComputerUi -> {
                viewModelScope.launch {
                    repository.deleteComputer(obj.id)
                        .onSuccess {
                            loadObjects()
                        }
                        .onFailure { t ->
                            updateState { it.copy(loadingStatus = LoadingStatus.Error(t.message)) }
                        }
                }
            }

            is ComponentUi -> {
                viewModelScope.launch {
                    repository.deleteComponent(obj.id)
                        .onSuccess {
                            loadObjects()
                        }
                        .onFailure { t ->
                            updateState { it.copy(loadingStatus = LoadingStatus.Error(t.message)) }
                        }
                }
            }
        }
    }

    private fun loadObjects() {
        updateState { it.copy(loadingStatus = LoadingStatus.Loading) }
        val jobs = mutableListOf<Job>()
        viewModelScope.launch {
            jobs.add(
                launch {
                    repository.getComputers()
                        .onSuccess { computers ->
                            updateState {
                                it.copy(computers = computers.map { c ->
                                    ComputerUi.fromComputer(
                                        c
                                    )
                                })
                            }
                        }
                        .onFailure { t ->
                            updateState {
                                it.copy(loadingStatus = LoadingStatus.Error(t.message))
                            }
                        }
                }
            )
            jobs.add(
                launch {
                    repository.getComponents()
                        .onSuccess { components ->
                            updateState {
                                it.copy(components = components.map { c ->
                                    ComponentUi.fromComponent(
                                        c
                                    )
                                })
                            }
                        }
                        .onFailure { t ->
                            updateState { it.copy(loadingStatus = LoadingStatus.Error(t.message)) }
                        }
                }
            )
            jobs.add(
                launch {
                    locationsRepo.locations()
                        .onSuccess { locations ->
                            updateState { it.copy(locations = locations.map { l -> LocationUi.from(l) }) }
                        }.onFailure { t ->
                            updateState { it.copy(loadingStatus = LoadingStatus.Error(t.message)) }
                        }
                }
            )
            jobs.forEach { it.join() }
            updateState { it.copy(loadingStatus = LoadingStatus.FullyLoad) }
        }
    }
}